package com.tbit.uqbike.webmanager.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.tbit.common.constant.MethodEnum;
import com.tbit.common.constant.ModuleEnum;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.common.enums.OperaPswEnum;
import com.tbit.common.utils.TraceUtil;
import com.tbit.config.tg.TbitAdminAccountInfo;
import com.tbit.uqbike.annos.OperateLog;
import com.tbit.uqbike.constant.OperaPswConstant;
import com.tbit.uqbike.constant.UserConstant;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.PageData;
import com.tbit.uqbike.object.pojo.Account;
import com.tbit.uqbike.object.pojo.BrandConfig;
import com.tbit.uqbike.object.pojo.HolderAccountBound;
import com.tbit.uqbike.object.pojo.dto.PasswordLoginDTO;
import com.tbit.uqbike.object.pojo.vo.CuServiceConfigVO;
import com.tbit.uqbike.object.pojo.vo.LoginLogVO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.uqbike.service.base.TokenService;
import com.tbit.uqbike.service.business.*;
import com.tbit.uqbike.service.event.EventType;
import com.tbit.uqbike.service.event.eventItem.AccountEvent;
import com.tbit.uqbike.service.rpcservice.SmsService;
import com.tbit.uqbike.webmanager.util.Assert;
import com.tbit.uqbike.webmanager.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;


@Slf4j
@Validated
@RestController
@RequestMapping(value = "/account", produces = BaseController.MEDIA_JSON_UTF8)
public class AccountController extends BaseController {

    @Autowired
    private AccountService accountService;
    @Autowired
    private BranConfigService branConfigService;
    @Autowired
    private HolderAccountBoundService holderAccountBoundService;
    @Autowired
    private AccountUserFreeLoginService freeLoginService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private OperaPswService operaPswService;
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    /**
     * 密码登录
     * @param dto 密码登录传输实体类
     * @param request
     * @return
     */
    @PostMapping("/loginWithPassword")
    public Result loginWithPassword(@RequestBody PasswordLoginDTO dto, HttpServletRequest request) {
        Assert.notNulls("参数有误", dto.getCountry(), dto.getPassword(), dto.getPhone(), dto.getLoginMethod(), dto.getPassword(), dto.getBrandId());
        String token = accountService.verifyPasswordLogin(dto.getCountry(), dto.getPhone(), dto.getPassword(), dto.getLoginMethod(), dto.getBrandId(), request);
        return Result.success(token);
    }

    /**
     * 请求方式:POST
     *
     * @param country 国际码 必传    传86
     * @param phone   登录手机号 必传， 前提：需要账号管理分配账号
     * @param code    短信下发的验证码
     * @return 结果 {
     * "data": "185103fb-f686-4878-b4a8-867d484df585",
     * "ret": 1
     * }
     * <p>
     * data值为当前用户请求接口所需的token
     */
    @RequestMapping("/loginWithCode")
    public JsonResult loginWithCode(@NotNull(message = "ver.brandId.notNull") Integer brandId,
                                    @NotNull(message = "ver.country.notNull") String country,
                                    @NotNull(message = "ver.phone.notNull") String phone,
                                    @NotNull(message = "ver.code.login.notNull") String code, HttpServletRequest request) {
        // 校验账号
        String token = accountService.verifyCodeLogin(brandId, country, phone, code, SmsService.CODE_LOGIN, request);
        LoginInfo loginInfo = tokenService.getLoginInfo(token);
        if (!phone.matches("^1[3-9]\\d{9}$")) {
            return JsonResult.fail("请输入正确的手机号", TraceUtil.getTraceIdByLocal());
        }

        //刷新最近登录时间
        freeLoginService.refreshLoginDate(loginInfo.getAccountUserId(), OperaPswConstant.TOKEN_EXPIRE_TIME, new Date());
        return JsonResult.ok(token);
    }

    /**
     * 内部系统登录
     * @param userName 用户名
     * @param nickName 姓名
     * @param timestamp 时间戳
     * @param secretStr 加密字符串
     * @param request request
     * @return token
     */
    @PostMapping("/loginWithSystem")
    public Result<String> loginWithSystem(String userName, String nickName, Long timestamp, String secretStr, HttpServletRequest request) {
        com.tbit.utils.Assert.notNulls("参数有误", userName, nickName, timestamp, secretStr);
        return accountService.loginWithSystem(userName, nickName, timestamp, secretStr, request);
    }

    @GetMapping("/login/log/list")
    public Result<PageResult<LoginLogVO>> loginLogListPage(String phone, String userName,
                                                           Long startTime, Long endTime,
                                                           @RequestParam(required = false, defaultValue = "1") Integer page,
                                                           @RequestParam(defaultValue = "10") Integer size, Integer accountId) {
        PageResult<LoginLogVO> result = accountService.selectAccountLoginLog(phone, userName, page, size, accountId, startTime, endTime);
        return Result.success(result);
    }

    @RequestMapping("/getAccountInfo")
    public JsonResult getAccountInfo(Integer accountId, HttpServletRequest request) {
        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        if (accountId == null) {
            accountId = loginInfo.id;
        }
        Account account = accountService.getAccountById(loginInfo, accountId);
        // 处理敏感信息
        if (null != account) {
            account.setPassword(null);
        }
        return JsonResult.ok(account);
    }

    //获取品牌信息
    @RequestMapping("/getBrandMsg")
    public JsonResult getBrandMsg(@NotNull(message = "ver.loginname.notBlank") String logoUrl, HttpServletRequest request) {
        BrandConfig brandConfig = branConfigService.getByUrl(logoUrl);

        return JsonResult.ok(brandConfig);
    }

    //设置品牌配置信息
    @RequestMapping("/insertBrandMsg")
    @OperateLog(module = ModuleEnum.ACCOUNT, methods = MethodEnum.BRAND_CONFIG_EDIT)
    public JsonResult insertBrandMsg(BrandConfig brandConfig, HttpServletRequest request) {
        LoginInfo loginInfo = getLogin(request);
        Assert.notNull(brandConfig.getLogoUrl(), "ver.logoUrl.notNull");
        Assert.notNull(brandConfig.getBrandHost(), "ver.brandHost.notNull");
        Assert.notNull(brandConfig.getBrandName(), "ver.brandName.notNull");
        Assert.notNull(brandConfig.getColor(), "ver.color.notNull");
        if (loginInfo.type.equals(UserConstant.USER_ADMIN)) {
            Assert.notNull(brandConfig.getAccountId(), "ver.accountId .notNull");
        }
        branConfigService.insert(brandConfig, loginInfo);

        return JsonResult.ok();
    }

    //修改密码
    @RequestMapping("/editPsd")
    @OperateLog(module = ModuleEnum.ACCOUNT, methods = MethodEnum.ACCOUNT_PAS_EDIT)
    public JsonResult editPsd(@NotNull(message = "ver.password.notNull") String password, HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        accountService.editPsd(info, password);
        return JsonResult.ok();
    }

    //获取列表
    @RequestMapping("/getAccountList")
    public JsonResult getAccountList(@NotNull(message = "ver.type.notNull") Integer type, Integer brands, String franchisees,
                                     HttpServletRequest request, Double version) {
        LoginInfo info = getLogin(request);
        if (type.equals(UserConstant.USER_CUS_HOLDER) || holderAccountBoundService.getCountByUserId(info.getAccountUserId()) > 0) {
            List<HolderAccountBound> list = holderAccountBoundService.getByAccountUserId(info.accountUserId);
            return JsonResult.ok(list);
        } else {
            List<Integer> franchiseIds = StringUtil.getIntegerList(franchisees);
            List<Account> accountList = accountService.getAccountList(info, type, brands, franchiseIds, version);
            return JsonResult.ok(accountList);
        }
    }

    //创建账号
    @RequestMapping("/insert")
    @OperateLog(module = ModuleEnum.ACCOUNT, methods = MethodEnum.ACCOUNT_ADD)
    public JsonResult editPsd(Account account, HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        //参数验证
        Assert.notNull(account.getName(), "ver.name.notNull");
        Assert.notNull(account.getType(), "ver.type.notNull");
        Assert.notNull(account.getParentId(), "ver.parentId.notNull");
        checkLength(account);
        if (account.getRemark() == null) {
            account.setRemark("");
        }

        accountService.insert(account, info);
        // 发布租户品牌创建事件
        eventPublisher.publishEvent(new AccountEvent(new TbitAdminAccountInfo(account.getName(), account.getAccountId()), EventType.ADD));
        return JsonResult.ok();
    }

    @GetMapping("/getBrandIdByAccountId/{accountId}")
    public Result<Integer> getBrandIdByAccountId(@PathVariable Integer accountId) {
        return Result.success(accountService.getBrandIdByAccountId(accountId));
    }

    //修改账号
    @RequestMapping("/edit")
    @OperateLog(module = ModuleEnum.ACCOUNT, methods = MethodEnum.ACCOUNT_EDIT)
    public JsonResult edit(Account account, Integer accountId, HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        //参数验证
        Assert.notNull(account.getAccountId(), "ver.accountId.notNull");
        checkLength(account);
        accountService.edit(account, info);
        return JsonResult.ok();
    }

    /**
     * 删除区域
     *
     * @param accountId 区域id
     * @param operaPsw  操作密码
     */
    @RequestMapping("/del")
    @OperateLog(module = ModuleEnum.ACCOUNT, methods = MethodEnum.ACCOUNT_DEL)
    public JsonResult del(@NotNull(message = "ver.accountId.notNull") Integer accountId, String operaPsw,
                          HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        /**操作密码校验*/
        operaPswService.checkOperaPsw(info, OperaPswEnum.OPERA_PSW_OPERATION_CONFIG.getModule(), operaPsw);

        accountService.del(accountId, info);

        return JsonResult.ok();
    }

    //修改品牌配置
    @RequestMapping("/editBrand")
    @OperateLog(module = ModuleEnum.ACCOUNT, methods = MethodEnum.BRAND_CONFIG_EDIT)
    public JsonResult editBrand(BrandConfig brandConfig, HttpServletRequest request) {
        Assert.notNull(brandConfig.getLogoUrl(), "ver.logoUrl.notNull");
        Assert.notNull(brandConfig.getBrandHost(), "ver.brandHost.notNull");
        Assert.notNull(brandConfig.getBrandName(), "ver.brandName.notNull");
        Assert.notNull(brandConfig.getColor(), "ver.color.notNull");
        LoginInfo info = getLogin(request);
        Assert.notNull(brandConfig.getAccountId(), "ver.accountId.notNull");
        branConfigService.editBrandConfig(brandConfig, info);

        return JsonResult.ok();
    }

    //获取品牌配置
    @RequestMapping("/getBrand")
    public JsonResult getBrand(@NotNull(message = "ver.accountId.notNull") Integer accountId,
                               HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        BrandConfig brandConfig = branConfigService.getByAccountId(info, accountId);

        return JsonResult.ok(brandConfig);
    }


    //获取所有运营区域
    @RequestMapping("/getOperationAccountIds")
    public JsonResult getOperationAccountIds(Integer accountId, HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        if (info.type.equals(UserConstant.USER_ADMIN)) {
            Assert.notNull(accountId, "ver.accountId .notNull");
        } else if (info.type.equals(UserConstant.USER_BRAND)) {
            accountId = info.id;
        } else {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        List<Account> accounts = accountService.getOperationAccountIds(accountId, info);

        return JsonResult.ok(accounts);
    }

    //获取所有账户列表
    @RequestMapping("/getAccounts")
    public JsonResult getAccounts(@NotNull(message = "ver.type.notNull") Integer type,
                                  String name, String phone, @RequestParam(defaultValue = "10") Integer rowCount,
                                  @RequestParam(defaultValue = "1") Integer pageNO, HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        Integer total = accountService.getTotal(name, phone, type, info);
        List<Account> accounts = accountService.getAccount(name, phone, type, rowCount, pageNO, info);

        return JsonResult.ok(accounts, total);
    }

    //获取当前角色的角色树
    @RequestMapping("/getAccountTree")
    public JsonResult getAccountTree(String name, Integer rowCount, Integer pageNO, HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        if (null == rowCount && null == pageNO) {
            // 全部获取
        } else {
            // 分页获取
            if (null == rowCount || rowCount <= 0 || rowCount > 1000) {
                rowCount = 20;
            }
            if (null == pageNO || pageNO < 1) {
                pageNO = 1;
            }
        }
        PageData<List<Account>> data = accountService.getAccountTree1(info, name, rowCount, pageNO);
        return JsonResult.ok(data.getData(), data.getTotal());
    }

    //模糊搜索
    @RequestMapping("/getByName")
    public JsonResult getByName(String name, HttpServletRequest request) {
        LoginInfo info = getLogin(request);
        List<Account> accounts = accountService.getByName(info, name);
        return JsonResult.ok(accounts);
    }

    /**
     * 获取父节点信息
     *
     * @return
     */
    @RequestMapping(value = "/getUp")
    public JsonResult getAgentUp(@NotNull(message = "ver.accountId.notNull") Integer accountId, HttpServletRequest request) {
        //调用业务层
        LoginInfo info = getLogin(request);

        List TreeNode = accountService.getUp(info, accountId);
        return JsonResult.ok(TreeNode);
    }

    /**
     * 根据域名获取品牌配置信息
     *
     * @param brandHost
     * @return
     */
    @RequestMapping(value = "/getBrandConfigByHost")
    public JsonResult getBrandConfigByHost(String brandHost) {
        Assert.hasLength(brandHost, "ver.brandHost.notNull");
        BrandConfig brandConfig = branConfigService.getByHost(brandHost);
        return JsonResult.ok(brandConfig);
    }

    /**
     * 根据品牌名称获取品牌配置信息
     *
     * @param brandName
     * @return
     */
    @RequestMapping(value = "/getBrandConfigByName")
    public JsonResult getBrandConfigByName(String brandName) {
        Assert.hasLength(brandName, "ver.brandName.notNull");
        BrandConfig brandConfig = branConfigService.getByName(brandName);
        return JsonResult.ok(brandConfig);
    }

    /**
     * 通过品牌id或加盟商id获取区域id
     *
     */
    @RequestMapping("/getByIdAndType")
    public JsonResult getByIdAndType(@NotNull(message = "ver.accountId.notNull") Integer accountId, @NotNull(message = "ver.type.notNull") Integer type, HttpServletRequest request) {
        List<Account> list = accountService.getByIdAndType(accountId, type);
        return JsonResult.ok(list);
    }

    void checkLength(Account account) {
        if (StrUtil.isNotEmpty(account.getName()) && account.getName().length() > 100) {
            throw new BaseException("新增名称过长");
        } else if (StrUtil.isNotEmpty(account.getPhone()) && account.getPhone().length() > 50) {
            throw new BaseException("新增手机号码过长");
        } else if (StrUtil.isNotEmpty(account.getEmail()) && account.getEmail().length() > 50) {
            throw new BaseException("新增邮箱过长");
        } else if (StrUtil.isNotEmpty(account.getRemark()) && account.getRemark().length() > 255) {
            throw new BaseException("新增备注过长");
        }
    }
    /**
     * @description: 编辑账户的客服配置信息
     * @author: mo.shanyong
     * @date: 2024/11/26 19:01
     * @param: accountConfigInfo
     * @param: request
     * @return: com.tbit.uqbike.object.view.JsonResult
     */
    @RequestMapping("/editAccountServiceInfo")
    public JsonResult editAccountServiceInfo(@RequestBody CuServiceConfigVO accountConfigInfo,HttpServletRequest request){
        Assert.notNull(accountConfigInfo,"参数不能为空");
        Assert.notNull(accountConfigInfo.getAccountId(),"账户id不能为空");
        Assert.notNull(accountConfigInfo.getName(),"账户名称不能为空");
        LoginInfo info = getLogin(request);
        log.info("accountConfigInfo:{}", JSON.toJSONString(accountConfigInfo));
        accountService.editAccountServiceInfo(accountConfigInfo,info);
        // 租户品牌变更事件
        eventPublisher.publishEvent(new AccountEvent(new TbitAdminAccountInfo(accountConfigInfo.getName(), accountConfigInfo.getAccountId()), EventType.UPDATE));
        return JsonResult.ok();
    }

    /**
     * @description: 通过当前登录用户，获取用户可以获取到的所有区域
     * @author: mo.shanyong
     * @date: 2025/2/27 15:55
     * @param: request
     * @return: com.tbit.uqbike.object.view.JsonResult
     */
    @GetMapping("/getAccountByLoginUser")
    public JsonResult getAccountByLoginUser(HttpServletRequest request){
        LoginInfo info = getLogin(request);
        List<Account> accountList = accountService.getAccountByLoginUser(info);
        return JsonResult.ok(accountList);
    }

    /**
     * 划拨区域：将当前区域划拨到另一个代理商下
     *
     * @param accountId 区域id
     * @param newAgent  划拨后代理商id
     */
    @PostMapping("/transferAccount")
    public Result<String> transferAccount(@NotNull Integer accountId, @NotNull Integer newAgent){
        accountService.transferAccount(accountId, newAgent);
        return Result.success();
    }

    /**
     * 根据区域id获取代理商列表:当前区域的代理商是代理商列表的第一个
     *
     * @param accountId 区域id
     */
    @GetMapping("/getAgentsByAccountId")
    public Result<List<Account>> getAgentsByAccountId(@NotNull Integer accountId){
        return Result.success(accountService.getAgentsByAccountId(accountId));
    }
}
